﻿#region using...
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Infusion.Silverlight.Controls.Ribbon;
#endregion

namespace Infusion.Silverlight.Controls.Input
{
    #region : DropDownList :
    #region Template Parts...
    [TemplatePart(Name = DropDownList.DropDownListLayoutRoot, Type = typeof(Grid))]
    [TemplatePart(Name = DropDownList.ImgIcon, Type = typeof(Image))]
    [TemplatePart(Name = DropDownList.TxtLabel, Type = typeof(TextBlock))]
    [TemplatePart(Name = DropDownList.DropDownListCanvas, Type = typeof(Canvas))]
    [TemplatePart(Name = DropDownList.DropDownListRectClip, Type = typeof(RectangleGeometry))]
    [TemplatePart(Name = DropDownList.DropDownListBorder, Type = typeof(Rectangle))]
    [TemplatePart(Name = DropDownList.TbxText, Type = typeof(TextBox))]
    [TemplatePart(Name = DropDownList.ButtonBorder, Type = typeof(Canvas))]
    [TemplatePart(Name = DropDownList.ButtonBackground, Type = typeof(Canvas))]
    [TemplatePart(Name = DropDownList.ButtonClickSurface, Type = typeof(Canvas))]
    #endregion
    public class DropDownList : RibbonTabGroupItem
    {
        #region TemplatePart Names...
        public const string DropDownListLayoutRoot = "DropDownListLayoutRoot";
        public const string ImgIcon = "ImgIcon";
        public const string TxtLabel = "TxtLabel";
        public const string DropDownListCanvas = "DropDownListCanvas";
        public const string DropDownListRectClip = "DropDownListRectClip";
        public const string DropDownListBorder = "DropDownListBorder";
        public const string TbxText = "TbxText";
        public const string ButtonBorder = "ButtonBorder";
        public const string ButtonBackground = "ButtonBackground";
        public const string ButtonClickSurface = "ButtonClickSurface";
        #endregion

        #region TemplatePart Variables...
        internal Grid dropDownListLayoutRoot;
        internal Image imgIcon;
        internal TextBlock txtLabel;
        internal Canvas dropDownListCanvas;
        internal RectangleGeometry dropDownListRectClip;
        internal Rectangle dropDownListBorder;
        internal TextBox tbxText;
        internal Canvas buttonBorder;
        internal Canvas buttonBackground;
        internal Canvas buttonClickSurface;
        #endregion

        #region Dependency Properties...
        #region TextProperty
        /// <summary>
        /// Identifies the Infusion.Silverlight.Controls.Input.DropDownList.Text dependency property.
        /// </summary>
        public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
            "Text",
            typeof(string),
            typeof(DropDownList),
            new PropertyMetadata(new PropertyChangedCallback(TextPropertyChanged)));
        #endregion

        #region ImageSourceProperty
        /// <summary>
        /// Identifies the Infusion.Silverlight.Controls.Input.DropDownList.ImageSource dependency property.
        /// </summary>
        public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.Register(
            "ImageSource",
            typeof(string),
            typeof(DropDownList),
            null);
        #endregion

        #region LabelProperty
        /// <summary>
        /// Identifies the Infusion.Silverlight.Controls.Input.DropDownList.Label dependency property.
        /// </summary>
        public static readonly DependencyProperty LabelProperty = DependencyProperty.Register(
            "Label",
            typeof(string),
            typeof(DropDownList),
            null);
        #endregion
        #endregion

        #region Dependency Property Changed Handlers...
        #region TextPropertyChanged
        private static void TextPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
        }
        #endregion
        #endregion

        #region Class Variables...
        private bool templateApplied = false;
        private bool textBoxHasFocus = false;
        private bool listOpen = false;
        #endregion

        #region Constructor(s)...
        #region DropDownList
        public DropDownList() : base()
        {
            DefaultStyleKey = typeof(DropDownList);
        }
        #endregion
        #endregion

        #region Event Handlers...
        #region dropDownListCanvas_SizeChanged
        private void dropDownListCanvas_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            //as the drop down changes size enusre that the clip and border are sized appropriately...
            dropDownListRectClip.Rect = new Rect(0, 0, dropDownListCanvas.Width, dropDownListCanvas.Height);
            dropDownListBorder.Width = dropDownListCanvas.Width + 1;
        }
        #endregion

        #region tbxText_MouseEnter
        private void tbxText_MouseEnter(object sender, MouseEventArgs e)
        {
            //change the background and border to appear highlighted...
            dropDownListCanvas.Background = Helper.GetBrush(SolidColorBrushes.DropDownListBackgroundHighlighted);
            dropDownListBorder.Stroke = Helper.GetBrush(SolidColorBrushes.DropDownListBorderHighlighted);

            //if the textbox does not have focus, change the button background and border so that it appears...
            if (!textBoxHasFocus)
            {
                buttonBorder.Background = Helper.GetBrush(SolidColorBrushes.DropDownListButtonBorder);
                buttonBackground.Background = Helper.GetBrush(LinearGradientBrushes.DropDownListButtonBackground);
            }
        }
        #endregion

        #region tbxText_MouseLeave
        private void tbxText_MouseLeave(object sender, MouseEventArgs e)
        {
            //if the textbox does not have focus...
            if (!textBoxHasFocus)
            {
                //change the background and border to appear in the normal state...
                dropDownListCanvas.Background = Helper.GetBrush(SolidColorBrushes.DropDownListBackground);
                dropDownListBorder.Stroke = Helper.GetBrush(SolidColorBrushes.DropDownListBorder);

                //hide the button background and border...
                buttonBorder.Background = Helper.GetBrush(SolidColorBrushes.Transparent);
                buttonBackground.Background = Helper.GetBrush(SolidColorBrushes.Transparent);
            }
        }
        #endregion

        #region tbxText_GotFocus
        private void tbxText_GotFocus(object sender, RoutedEventArgs e)
        {
            textBoxHasFocus = true;

            //change the background and border to appear highlighted...
            dropDownListCanvas.Background = Helper.GetBrush(SolidColorBrushes.DropDownListBackgroundHighlighted);
            dropDownListBorder.Stroke = Helper.GetBrush(SolidColorBrushes.DropDownListBorderHighlighted);

            if (!listOpen)
            {
                //if the drop down list is not open, set the button to it's highlighted state...
                buttonBorder.Background = Helper.GetBrush(SolidColorBrushes.DropDownListButtonBorderHighlighted);
                buttonBackground.Background = Helper.GetBrush(LinearGradientBrushes.DropDownListButtonBackgroundHighlighted);
            }
            else
            {
                //if the drop down list is open, set the button to it's selected state...
                buttonBorder.Background = Helper.GetBrush(SolidColorBrushes.DropDownListButtonBorderSelected);
                buttonBackground.Background = Helper.GetBrush(LinearGradientBrushes.DropDownListButtonBackgroundSelected);
            }
        }
        #endregion

        #region tbxText_LostFocus
        private void tbxText_LostFocus(object sender, RoutedEventArgs e)
        {
            textBoxHasFocus = false;
            listOpen = false;

            //reset the background and border to the normal state...
            dropDownListCanvas.Background = Helper.GetBrush(SolidColorBrushes.DropDownListBackground);
            dropDownListBorder.Stroke = Helper.GetBrush(SolidColorBrushes.DropDownListBorder);

            //hide the button background and border...
            buttonBorder.Background = Helper.GetBrush(SolidColorBrushes.Transparent);
            buttonBackground.Background = Helper.GetBrush(SolidColorBrushes.Transparent);
        }
        #endregion

        #region buttonClickSurface_MouseEnter
        private void buttonClickSurface_MouseEnter(object sender, MouseEventArgs e)
        {
            //if the textbox does not have focus...
            if (!textBoxHasFocus)
            {
                //...change the checkbox background and border to appear highlighted...
                dropDownListCanvas.Background = Helper.GetBrush(SolidColorBrushes.DropDownListBackgroundHighlighted);
                dropDownListBorder.Stroke = Helper.GetBrush(SolidColorBrushes.DropDownListBorderHighlighted);

                //...change the button background and border to appear highlighted...
                buttonBorder.Background = Helper.GetBrush(SolidColorBrushes.DropDownListButtonBorderHighlighted);
                buttonBackground.Background = Helper.GetBrush(LinearGradientBrushes.DropDownListButtonBackgroundHighlighted);
            }
        }
        #endregion

        #region buttonClickSurface_MouseLeave
        private void buttonClickSurface_MouseLeave(object sender, MouseEventArgs e)
        {
            //if the textbox does not have focus...
            if (!textBoxHasFocus)
            {
                //...reset the background and border to the normal state...
                dropDownListCanvas.Background = Helper.GetBrush(SolidColorBrushes.DropDownListBackground);
                dropDownListBorder.Stroke = Helper.GetBrush(SolidColorBrushes.DropDownListBorder);

                //...hide the button bacground and border...
                buttonBorder.Background = Helper.GetBrush(SolidColorBrushes.Transparent);
                buttonBackground.Background = Helper.GetBrush(SolidColorBrushes.Transparent);
            }
        }
        #endregion

        #region buttonClickSurface_MouseLeftButtonDown
        private void buttonClickSurface_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            //toggle the state of the drop down item list...
            ToggleList();            
        }
        #endregion

        #region tbxText_KeyDown
        private void tbxText_KeyDown(object sender, KeyEventArgs e)
        {
            //if the item list is close and the down arrow is pressed or...
            //...the item list is open and the escape key is pressed...
            if ((e.Key == Key.Down && !listOpen) || (e.Key == Key.Escape && listOpen))
            {
                //toggle the state of the drop down item list...
                e.Handled = true;
                ToggleList();
            }
        }
        #endregion
        #endregion

        #region Methods...
        #region ToggleList
        private void ToggleList()
        {
            //toggle the state of the item list...
            listOpen = !listOpen;

            if (listOpen)
            {
                if (textBoxHasFocus)
                {
                    //change the button background and border to appear selected...
                    buttonBorder.Background = Helper.GetBrush(SolidColorBrushes.DropDownListButtonBorderSelected);
                    buttonBackground.Background = Helper.GetBrush(LinearGradientBrushes.DropDownListButtonBackgroundSelected);
                }
                else
                {
                    //set focus on textbox...
                    tbxText.Focus();
                }

                //select all the text in the textbox...
                tbxText.Select(0, tbxText.Text.Length);
            }
            else
            {
                //de-select any selected text...
                tbxText.Select(0, 0);

                //change the button background and border to appear highlighted...
                buttonBorder.Background = Helper.GetBrush(SolidColorBrushes.DropDownListButtonBorderHighlighted);
                buttonBackground.Background = Helper.GetBrush(LinearGradientBrushes.DropDownListButtonBackgroundHighlighted);
            }
        }
        #endregion

        #region OnApplyTemplate
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            if (!templateApplied)
            {
                //get template children...
                dropDownListLayoutRoot = (Grid)GetTemplateChild(DropDownListLayoutRoot);
                imgIcon = (Image)GetTemplateChild(ImgIcon);
                txtLabel = (TextBlock)GetTemplateChild(TxtLabel);
                dropDownListCanvas = (Canvas)GetTemplateChild(DropDownListCanvas);
                dropDownListRectClip = (RectangleGeometry)GetTemplateChild(DropDownListRectClip);
                dropDownListBorder = (Rectangle)GetTemplateChild(DropDownListBorder);
                tbxText = (TextBox)GetTemplateChild(TbxText);
                buttonBorder = (Canvas)GetTemplateChild(ButtonBorder);
                buttonBackground = (Canvas)GetTemplateChild(ButtonBackground);
                buttonClickSurface = (Canvas)GetTemplateChild(ButtonClickSurface);

                //drop doen list event handlers...
                dropDownListCanvas.SizeChanged += new SizeChangedEventHandler(dropDownListCanvas_SizeChanged);

                //textbox mouse, focus and key event handlers...
                tbxText.MouseEnter += new MouseEventHandler(tbxText_MouseEnter);
                tbxText.MouseLeave += new MouseEventHandler(tbxText_MouseLeave);
                tbxText.GotFocus += new RoutedEventHandler(tbxText_GotFocus);
                tbxText.LostFocus += new RoutedEventHandler(tbxText_LostFocus);
                tbxText.KeyDown += new KeyEventHandler(tbxText_KeyDown);

                //button mouse event handlers...
                buttonClickSurface.MouseEnter += new MouseEventHandler(buttonClickSurface_MouseEnter);
                buttonClickSurface.MouseLeave += new MouseEventHandler(buttonClickSurface_MouseLeave);
                buttonClickSurface.MouseLeftButtonDown += new MouseButtonEventHandler(buttonClickSurface_MouseLeftButtonDown);

                //if text is set by default apply it to the textbox...
                if (!string.IsNullOrEmpty(Text))
                {
                    tbxText.Text = Text;
                }

                //if a label is specified by default, set the label of the control...
                if (!string.IsNullOrEmpty(Label))
                {
                    txtLabel.Text = Label;
                }
                else
                {
                    //...otherwise remove any padding...
                    txtLabel.Margin = new Thickness(0);
                }

                //if an imagesource is specified by default, set the icon source and containing column width...
                if (!string.IsNullOrEmpty(ImageSource))
                {
                    dropDownListLayoutRoot.ColumnDefinitions[0].Width = new GridLength(22);
                    imgIcon.Source = new BitmapImage(new Uri(ImageSource, UriKind.Relative));
                }
                else
                {
                    //...otherwise ensure the containing column has zero width...
                    dropDownListLayoutRoot.ColumnDefinitions[0].Width = new GridLength(0);
                }

                templateApplied = true;
            }
        }
        #endregion
        #endregion

        #region Properties...
        #region RealWidth
        /// <summary>
        /// Gets the rendered width of the control including image and label if any...
        /// </summary>
        public override double RealWidth
        {
            get
            {
                return (!string.IsNullOrEmpty(ImageSource) ? 22 : 0) +
                    (!string.IsNullOrEmpty(Label) ? txtLabel.ActualWidth + 4 : 0) +
                    dropDownListLayoutRoot.ActualWidth;
            }
        }
        #endregion

        #region Text
        /// <summary>
        /// Gets or sets the current text...
        /// </summary>
        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }
        #endregion

        #region Label
        /// <summary>
        /// Gets or sets a label to describe the drop down list...
        /// </summary>
        public string Label
        {
            get { return (string)GetValue(LabelProperty); }
            set { SetValue(LabelProperty, value); }
        }
        #endregion

        #region ImageSource
        /// <summary>
        /// Gets or sets the imagesource of the associated icon...
        /// </summary>
        public string ImageSource
        {
            get { return (string)GetValue(ImageSourceProperty); }
            set { SetValue(ImageSourceProperty, value); }
        }
        #endregion
        #endregion
    }
    #endregion
}